﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CruzDelSur.Models;
using CruzDelSur.Dominio;
using CruzDelSur.Dominio.Seguridad;
using CruzDelSur.Persistencia;
using System.Web.Mvc;
using System.Data.SqlTypes;
using System.Globalization;

namespace CruzDelSur.Negocio
{
    public class ServiciosEspecialesService
    {
        IServicioDAO ServicioDAO { get; set; }
        IConvenioDAO ConvenioDAO {get; set; }
        IClienteDAO ClienteDAO { get; set; }
        IContratoDAO ContratoDAO { get; set; }
        IPromocionDAO PromocionDAO { get; set; }
        IProyectoEspecialDAO ProyectoEspecialDAO { get; set; }
        ITramoDAO TramoDAO { get; set; }
        public ReporteEspecialesDAO ReporteEspecialesDAO { get; set; }
        public ServiciosEspecialesService() {
            ReporteEspecialesDAO = new ReporteEspecialesDAO();
        }
        #region Convenios

        public Convenio obtenerConvenio(string codigo)
        {
            return ConvenioDAO.Obtener(codigo);
        }

        public bool darBajaConvenio(Convenio convenio)
        {
            if (convenio.Codigo.Trim().Equals(""))
            {
                throw new CodigoInvalidoException("Debe ingresar un código válido");
            }
            //Regla de negocio - SE_RN_12
            if (!this.RN_FechaBajaValido(convenio.FechaBaja))
            {
                throw new FechaBajaServicioInvalidoException("Las bajas de convenios deben tener una fecha de inicio de baja mayor por 2 meses al día que se registra la baja");
            }
            Convenio s = ConvenioDAO.Obtener(convenio.Codigo);
            if (s != null)
            {
                s.FechaBaja = convenio.FechaBaja;
                s.FechaModificado = DateTime.Now;
                s.Estado = Servicio.INACTIVO;
                ConvenioDAO.Modificar(s);
            }
            else
            {
                throw new CodigoInvalidoException("Código no existe");
            }
            return true;
        }

        public ConvenioFormModel crearNuevoConvenioModel()
        {
            ConvenioFormModel model = new ConvenioFormModel();
            model.Convenio = new Convenio
            {
                FechaFirma = DateTime.Now,
                FechaVigencia = DateTime.Now.AddMonths(6),
                Estado = Servicio.PENDIENTE
            };
            model.Clientes = obtenerComboClientes(int.MinValue);
            model.EstadoEdicion = "CREAR";
            return model;
        }

        public ConvenioFormModel abrirConvenioModel(string codConvenio)
        {
            Convenio convenio = ConvenioDAO.obtenerConvenioDetalle(codConvenio);
            return new ConvenioFormModel
            {
                Convenio = convenio,
                Clientes = obtenerComboClientes(convenio.Cliente.Codigo),
                EstadoEdicion = "EDITAR"
            };
        }
        #endregion
        #region Proyectos especiales
        public ProyectoEspecialFormModel crearNuevoProyectoEspecialModel()
        {
            ProyectoEspecialFormModel model = new ProyectoEspecialFormModel();
            model.Cabecera = new ProyectoEspecial
            {
                 //= DateTime.Now,
                Detalle = new List<ProyectoEspecialDetalle>(),
                Estado = Servicio.PENDIENTE,
            };
            model.Clientes = obtenerComboClientes(int.MinValue);
            model.Detalle = new List<ProyectoEspecialDetalleFormModel>();
            model.EstadoEdicion = "CREAR";
            return model;
        }

        public ProyectoEspecialFormModel procesarProyectoEspecialModel(ProyectoEspecialFormModel procesado)
        {
            if (procesado.Cabecera.Detalle == null)
            {
                procesado.Cabecera.Detalle = new List<ProyectoEspecialDetalle>();
            }
            procesado.Detalle = new List<ProyectoEspecialDetalleFormModel>();
            procesado.Clientes = obtenerComboClientes(procesado.Cabecera.Cliente.Codigo);
            foreach (var item in procesado.Cabecera.Detalle)
            {
                procesado.Detalle.Add(new ProyectoEspecialDetalleFormModel
                {
                    Item = item,
                    Servicios = obtenerComboServiciosEspeciales(item.Servicio),
                    Tramos = obtenerComboServicioTramos(item.Servicio, item.Tramo)
                });
            }
            return procesado;
        }

        public ProyectoEspecialFormModel abrirProyectoEspecialModel(string codigo)
        {
            ProyectoEspecialFormModel model = crearNuevoProyectoEspecialModel();
            ProyectoEspecial proyEsp = ProyectoEspecialDAO.obtenerProyectoEspecialDetalle(codigo);
            model.Cabecera = proyEsp;
            model.Clientes = obtenerComboClientes(proyEsp.Cliente.Codigo);
            model.EstadoEdicion = "EDITAR";
            foreach (var item in proyEsp.Detalle)
            {
                model.Detalle.Add(new ProyectoEspecialDetalleFormModel
                {
                    Item = item,
                    Servicios = obtenerComboServiciosEspeciales(item.Servicio),
                    Tramos = obtenerComboServicioTramos(item.Servicio, item.Tramo),
                });
            }
            return model;
        }

        public SelectList obtenerComboServicioTramos(string codServ, string codTramo)
        {
            return new SelectList(obtenerListaServicioTramos(codServ), "Codigo", "Descripcion", codTramo);
        }

        public ICollection<Tramo> obtenerListaServicioTramos(string codServ)
        {
            return TramoDAO.ListarServicioTramos(codServ);
        }

        /// <summary>
        /// Metodo Crear nuevo ProyectoEspecial
        /// </summary>
        /// <param name="proyectoEspecial">Objeto de dominio ProyectoEspecial</param>
        /// <returns>ProyectoEspecial</returns>
        public ProyectoEspecial crearProyectoEspecial(ProyectoEspecial proyectoEspecial)
        {
            if (String.IsNullOrEmpty(proyectoEspecial.Codigo))
            {
                throw new DatoInvalidoException("Debe ingresar un código de proyecto especial");
            }
            if (obtenerProyectoEspecial(proyectoEspecial.Codigo) != null)
            {
                throw new CodigoExistenteException("Código de proyecto especial ya existe");
            }
            if (validarProyectoEspecial(proyectoEspecial))
            {
                proyectoEspecial.Cliente = ClienteDAO.Obtener(proyectoEspecial.Cliente.Codigo);
                proyectoEspecial.FechaCreado = DateTime.Now;
                proyectoEspecial.FechaModificado = SqlDateTime.MinValue.Value;
                proyectoEspecial.Estado = Servicio.PENDIENTE;
                ProyectoEspecialDAO.Crear(proyectoEspecial);
                ProyectoEspecialDAO.guardarDetalle(proyectoEspecial);
                return proyectoEspecial;
            }
            else return null;
        }

        public ProyectoEspecial modificarProyectoEspecial(ProyectoEspecial nuevoProyEsp)
        {
            if (validarProyectoEspecial(nuevoProyEsp))
            {
                ProyectoEspecial editProyEsp = ProyectoEspecialDAO.Obtener(nuevoProyEsp.Codigo);
                editProyEsp.Cliente = ClienteDAO.Obtener(nuevoProyEsp.Cliente.Codigo);
                editProyEsp.Descripcion = nuevoProyEsp.Descripcion;
                editProyEsp.Estado = Servicio.PENDIENTE;
                editProyEsp.ModificadoPor = nuevoProyEsp.ModificadoPor;
                editProyEsp.FechaModificado = DateTime.Now;
                editProyEsp.FechaModificado = DateTime.Now;
                ProyectoEspecialDAO.Modificar(editProyEsp);
                ProyectoEspecialDAO.guardarDetalle(nuevoProyEsp);
                return editProyEsp;
            }
            else return null;
        }
        /// <summary>
        /// Agregar un detalle de proyecto especial
        /// </summary>
        /// <returns>ProyectoEspecialDetalle</returns>
        public ProyectoEspecialDetalleFormModel AdicionarProyectoEspecialDetalleItem()
        {
            return new ProyectoEspecialDetalleFormModel
            {
                Item = new ProyectoEspecialDetalle
                {
                    Id = DateTime.Now.Millisecond,
                    FechaViaje = DateTime.Now,
                    HoraPartida = DateTime.Now
                },
                Servicios = obtenerComboServiciosEspeciales(String.Empty),
                Tramos = obtenerComboServicioTramos(String.Empty, String.Empty)
            };
        }

        public ProyectoEspecial obtenerProyectoEspecial(string codigo)
        {
            return ProyectoEspecialDAO.Obtener(codigo);
        }

        public bool darBajaProyectoEspecial(ProyectoEspecial pry)
        {
            if (pry.Codigo.Trim().Equals(""))
            {
                throw new CodigoInvalidoException("Debe ingresar un código válido");
            }
            ProyectoEspecial p = ProyectoEspecialDAO.Obtener(pry.Codigo);
            if (p != null)
            {
                p.FechaModificado = DateTime.Now;
                p.Estado = Servicio.INACTIVO;
                ProyectoEspecialDAO.Modificar(p);
            }
            else
            {
                throw new CodigoInvalidoException("Código no existe");
            }
            return true;
        }


        #endregion

        public SelectList obtenerComboClientes(int selectedValue)
        {
            return new SelectList(ClienteDAO.listarClientes(), "Codigo", "Nombre", selectedValue);
        }

        public SelectList obtenerComboServicios(string selected)
        {
            return new SelectList(ServicioDAO.ListarServicios(), "Codigo", "Descripcion", selected);
        }
        public SelectList obtenerComboServiciosEspeciales(string selected)
        {
            if (string.IsNullOrEmpty(selected))
            {
                ICollection<Servicio> items = ServicioDAO.ListarServiciosEspeciales();
                items.Add(new Servicio { Codigo="", Descripcion="[Seleccione un servicio]" });
                return new SelectList(items, "Codigo", "Descripcion", selected);
            } 
            else
                return new SelectList(ServicioDAO.ListarServiciosEspeciales(), "Codigo", "Descripcion", selected);
        }
        
        public SelectList obtenerComboTramos(string selected)
        {
            return new SelectList(TramoDAO.ListarTramos(), "Codigo", "Descripcion", selected);
        }
        #region Convenios
        /// <summary>
        /// Metodo Crear nuevo convenio
        /// </summary>
        /// <param name="nuevoConvenio">Objeto de dominio Convenio</param>
        /// <returns>Convenio</returns>
        public Convenio crearConvenio(Convenio nuevoConvenio)
        {
            //Verificar si codigo no es nulo
            if (String.IsNullOrEmpty(nuevoConvenio.Codigo))
            {
                throw new DatoInvalidoException("Debe ingresar un código válido");
            }
            if (obtenerConvenio(nuevoConvenio.Codigo) != null)
            {
                throw new CodigoExistenteException("El código de convenio ya existe");
            }
            if (validarConvenio(nuevoConvenio))
            {
                nuevoConvenio.Cliente = ClienteDAO.Obtener(nuevoConvenio.Cliente.Codigo);
                nuevoConvenio.FechaCreado = DateTime.Now;
                nuevoConvenio.FechaModificado = SqlDateTime.MinValue.Value;
                nuevoConvenio.FechaBaja = SqlDateTime.MinValue.Value;
                //Ahora invoco a mi clase DAO, devuelve a la controladora
                ConvenioDAO.Crear(nuevoConvenio);
                ConvenioDAO.guardarDetalle(nuevoConvenio);
                return nuevoConvenio;
            }
            else return null;   
        }

        public Convenio modificarConvenio(Convenio nuevoConvenio)
        {
            if (validarConvenio(nuevoConvenio))
            {
                Convenio editConvenio = ConvenioDAO.Obtener(nuevoConvenio.Codigo);
                editConvenio.Cliente = ClienteDAO.Obtener(nuevoConvenio.Cliente.Codigo);
                editConvenio.Descripcion = nuevoConvenio.Descripcion;
                editConvenio.FechaFirma = nuevoConvenio.FechaFirma;
                editConvenio.FechaVigencia = nuevoConvenio.FechaVigencia;
                editConvenio.NombreFuncionario = nuevoConvenio.NombreFuncionario;
                editConvenio.FechaModificado = DateTime.Now;
                ConvenioDAO.Modificar(editConvenio);
                ConvenioDAO.guardarDetalle(nuevoConvenio);
                return editConvenio;
            } return null;
        }

        public ListadoConveniosModel obtenerListadoConvenios()
        {
            return new ListadoConveniosModel
            {
                Convenios = ConvenioDAO.obtenerListado()
            };
        }

        public ConvenioDetalle AdicionarConvenioDetalleItem()
        {
            return new ConvenioDetalle
            {
                id = DateTime.Now.Millisecond,
                FlagExoneracionPago = false
            };
        }

        #region Contratos

        public ContratosModel crearNuevoContratoModel()
        {
            ContratosModel model = new ContratosModel();
            model.Contrato = new Contrato();
            model.Contrato.FechaInicioContrato = DateTime.Now;
            model.Contrato.FechaFinContrato = DateTime.Now;
            model.Contrato.Estado = Servicio.PENDIENTE;
            model.Clientes = new SelectList(ClienteDAO.listarClientes(), "Codigo", "Nombre");
            model.Detalle = new List<ContratoDetalleModel>();
            return model;
        }

        public ContratosModel abrirContratoModel(string codContrato)
        {
            ContratosModel model = crearNuevoContratoModel();
            Contrato contrato = ContratoDAO.obtenerContratoDetalle(codContrato);
            model.Contrato = contrato;
            model.Clientes = obtenerComboClientes(contrato.Cliente.Codigo);
            model.Detalle = new List<ContratoDetalleModel>();
            foreach (var item in contrato.Detalle)
            {
                model.Detalle.Add(new ContratoDetalleModel
                {
                    Item = item,
                    Servicios = obtenerComboServicios(item.Servicio),
                    Tramos = obtenerComboTramos(item.Tramo)
                });
            }
            return model;
        }

        public Contrato crearContrato(Contrato nuevoContrato)
        {
            if (validarContrato(nuevoContrato))
            {
                if (obtenerContrato(nuevoContrato.Codigo) != null)
                {
                    throw new CodigoExistenteException("Código de contrato ya existe");
                }
                nuevoContrato.FechaCreado = DateTime.Now;
                nuevoContrato.FechaModificado = SqlDateTime.MinValue.Value;
                nuevoContrato.FechaBaja = SqlDateTime.MinValue.Value;
                ContratoDAO.Crear(nuevoContrato);
                ContratoDAO.guardarDetalle(nuevoContrato);
                return nuevoContrato;
            }
            else return null;
        }

        public ListadoContratosModel obtenerListadoContratos()
        {
            return new ListadoContratosModel
            {
                Contratos = ContratoDAO.obtenerListado()
            };
        }

        public Contrato modificarContrato(Contrato nuevoContrato)
        {
            if (validarContrato(nuevoContrato))
            {
                Contrato editContrato = ContratoDAO.Obtener(nuevoContrato.Codigo);
                editContrato.Cliente = ClienteDAO.Obtener(nuevoContrato.Cliente.Codigo);
                editContrato.Descripcion = nuevoContrato.Descripcion;
                editContrato.FechaFinContrato = nuevoContrato.FechaFinContrato;
                editContrato.FechaInicioContrato = nuevoContrato.FechaInicioContrato;
                editContrato.FechaBaja = SqlDateTime.MinValue.Value;
                editContrato.FechaModificado = DateTime.Now;
                ContratoDAO.Modificar(editContrato);
                ContratoDAO.guardarDetalle(nuevoContrato);
                return editContrato;
            }
            else return null;
        }

        public ContratoDetalleModel AdicionarContratoDetalleItem()
        {
            return new ContratoDetalleModel
            {
                Item = new ContratoDetalle
                {
                    Id = DateTime.Now.Millisecond,
                    HoraPartida = DateTime.Now
                },
                Servicios = obtenerComboServicios(String.Empty),
                Tramos = obtenerComboTramos(String.Empty)
            };
        }

        public bool darBajaContrato(string codigo, DateTime fecha, Usuario user)
        {
            if (codigo.Trim().Equals(""))
            {
                throw new CodigoInvalidoException("Debe ingresar un código válido");
            }
            //Regla de negocio - SE_RN_12
            if (!this.RN_FechaBajaValido(fecha))
            {
                throw new FechaBajaServicioInvalidoException("Las bajas de contratos deben tener una fecha de inicio de baja mayor por 2 meses al día que se registra la baja");
            }
            Contrato s = ContratoDAO.Obtener(codigo);
            if (s != null)
            {
                //ServicioTramoDAO.DarBaja(s.Codigo, s.FechaBaja);
                s.FechaBaja = fecha;
                s.FechaModificado = DateTime.Now;
                s.Modificadopor = user.Codigo;
                s.Estado = Servicio.INACTIVO;
                ContratoDAO.Modificar(s);
            }
            else
            {
                throw new CodigoInvalidoException("Código no existe");
            }
            return true;
        }

        public ContratosModel darBajaContratoModel(string codContrato, ContratoEstadoEnum estado)
        {
            ContratosModel model = new ContratosModel
            {
                Contrato = obtenerContrato(codContrato),
                EstadoEdicion = estado,
            };
            model.Contrato.FechaBaja = DateTime.Now.AddMonths(2);
            return model;
        }

        public Contrato obtenerContrato(string Codigo)
        {
            return ContratoDAO.Obtener(Codigo);
        }
                
        #endregion

        public string formatoFecha()
        {
            string format = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.ToLower();
            return format.Replace("yyyy", "yy");
        }

        public bool RN_FechaBajaValido(DateTime fecha)
        {
            return fecha >= DateTime.Now.AddMonths(2);
        }

        #endregion

        #region SECCION PARA APROBAR ENTIDADES
        public void aprobarServicioEspecial(AprobarServicioEspecialFormModel model)
        {
            foreach (AprobarServicioEspecialDetalleModel d in model.Detalle)
            {
                if (d.Marcado)
                {
                    switch (model.TipoServicio) {
                        case 1:
                            PromocionDAO.CambiarEstado(d.Codigo, Servicio.ACTIVO);
                            break;
                        case 2:
                            ContratoDAO.CambiarEstado(d.Codigo, Servicio.ACTIVO);
                            break;
                        case 3:
                            ConvenioDAO.CambiarEstado(d.Codigo, Servicio.ACTIVO);
                            break;
                        case 4:
                            ProyectoEspecialDAO.CambiarEstado(d.Codigo, Servicio.ACTIVO);
                            break;
                    }
                }
            }
        }

        public AprobarServicioEspecialFormModel aprobarServicioEspecialFormModel(int tipoServicio)
        {
            AprobarServicioEspecialFormModel model = new AprobarServicioEspecialFormModel(tipoServicio);
            switch (tipoServicio)
            {
                case 1:
                    ICollection<Promocion> lista1 = PromocionDAO.obtenerListadoPendientes();
                    foreach (Promocion c in lista1)
                    {
                        model.agregarItem(c.Codigo, c.Descripcion, tipoServicio, false);
                    }
                    break;
                case 2:
                    ICollection<Contrato> lista2 = ContratoDAO.obtenerListadoPendientes();
                    foreach (Contrato c in lista2)
                    {
                        model.agregarItem(c.Codigo, c.Descripcion, tipoServicio, false);
                    }
                    break;
                case 3:
                    ICollection<Convenio> lista3 = ConvenioDAO.obtenerListadoPendientes();
                    foreach (Convenio c in lista3)
                    {
                        model.agregarItem(c.Codigo, c.Descripcion, tipoServicio, false);
                    }
                    break;
                case 4:
                    ICollection<ProyectoEspecial> lista4 = ProyectoEspecialDAO.obtenerListadoPendientes();
                    foreach (ProyectoEspecial c in lista4)
                    {
                        model.agregarItem(c.Codigo, c.Descripcion, tipoServicio, false);
                    }
                    break;
            }
            return model;
        }
#endregion

        //DESARROLLADO X VICTOR
        #region Promociones
        public bool darBajaPromocion(Promocion promocion)
        {
            if (promocion.Codigo.Trim().Equals(""))
            {
                throw new CodigoInvalidoException("Debe ingresar un código válido");
            }
            //Regla de negocio - SE_RN_12
            if (!this.RN_FechaBajaValido(promocion.FechaBaja))
            {
                throw new FechaBajaServicioInvalidoException("Las bajas de promoción deben tener una fecha de inicio de baja mayor por 2 meses al día que se registra la baja");
            }
            Promocion p = PromocionDAO.Obtener(promocion.Codigo);
            if (p != null)
            {
                p.FechaBaja = promocion.FechaBaja;
                p.FechaModificacion = DateTime.Now;
                p.Estado = Servicio.INACTIVO;
                PromocionDAO.Modificar(p);
            }
            else
            {
                throw new CodigoInvalidoException("Código no existe");
            }
            return true;
        }

        public PromocionesModel darBajaPromocionModel(string codPromocion, PromocionEstadoEnum estado)
        {
            PromocionesModel model = new PromocionesModel
            {
                Promocion = obtenerPromocion(codPromocion),
                EstadoEdicion = estado,
            };
            model.Promocion.FechaBaja = DateTime.Now.AddMonths(2);
            return model;
        }

        public Promocion obtenerPromocion(string Codigo)
        {
            return PromocionDAO.Obtener(Codigo);
        }

        public ListadoPromocionesModel obtenerListadoPromociones()
        {
            return new ListadoPromocionesModel
            {
                Promociones = PromocionDAO.obtenerListado()
            };
        }

        public PromocionesModel crearNuevoPromocionModel()
        {
            PromocionesModel model = new PromocionesModel();
            model.Promocion = new Promocion();
            model.Promocion.FechaInicio = DateTime.Now;
            model.Promocion.FechaFin = DateTime.Now;
            model.Promocion.Estado = Servicio.PENDIENTE;
            //model.Promocion = new SelectList(ClienteDAO.listarClientes(), "Codigo", "Nombre");
            model.Detalle = new List<PromocionDetalleModel>();
            model.EstadoEdicion = PromocionEstadoEnum.NUEVO;
            return model;
        }

        public Promocion crearPromocion(Promocion nuevoPromocion)
        {
            if (validarPromocion(nuevoPromocion))
            {
                if (obtenerPromocion(nuevoPromocion.Codigo) != null)
                {
                    throw new CodigoExistenteException("Código de promoción ya existe");
                }
                nuevoPromocion.FechaCreacion = DateTime.Now;
                nuevoPromocion.FechaModificacion = SqlDateTime.MinValue.Value;
                nuevoPromocion.FechaBaja = SqlDateTime.MinValue.Value;
                PromocionDAO.Crear(nuevoPromocion);
                PromocionDAO.guardarDetalle(nuevoPromocion);
                return nuevoPromocion;
            }
            else return null;
        }

        public PromocionesModel abrirPromocionModel(string codPromocion)
        {
            PromocionesModel model = crearNuevoPromocionModel();
            Promocion promocion = PromocionDAO.obtenerPromocionDetalle(codPromocion);
            model.Promocion = promocion;
            //model.Clientes = obtenerComboClientes(contrato.Cliente.Codigo);
            model.Detalle = new List<PromocionDetalleModel>();
            foreach (var item in promocion.Detalle)
            {
                item.Estado = promocion.Estado;
                model.Detalle.Add(new PromocionDetalleModel
                {
                    Item = item,
                    Servicios = obtenerComboServicios(item.Servicio),
                    Tramos = obtenerComboTramos(item.Tramo)
                });
            }
            model.EstadoEdicion = PromocionEstadoEnum.EDITAR;
            return model;
        }

        public Promocion modificarPromocion(Promocion nuevoPromocion)
        {
            if (validarPromocion(nuevoPromocion))
            {
                Promocion editPromocion = PromocionDAO.Obtener(nuevoPromocion.Codigo);
                //editPromocion.Cliente = ClienteDAO.Obtener(nuevoPromocion.Cliente.Codigo);
                editPromocion.Descripcion = nuevoPromocion.Descripcion;
                editPromocion.FechaFin = nuevoPromocion.FechaFin;
                editPromocion.FechaInicio = nuevoPromocion.FechaInicio;
                editPromocion.FechaBaja = SqlDateTime.MinValue.Value;
                editPromocion.FechaModificacion = DateTime.Now;
                PromocionDAO.Modificar(editPromocion);
                PromocionDAO.guardarDetalle(nuevoPromocion);
                return editPromocion;
            }
            else return null;
        }

        public PromocionDetalleModel AdicionarPromocionDetalleItem()
        {
            return new PromocionDetalleModel
            {
                Item = new PromocionDetalle
                {
                    Id = DateTime.Now.Millisecond,
                    //HoraPartida = DateTime.Now
                },
                Servicios = obtenerComboServicios(String.Empty),
                Tramos = obtenerComboTramos(String.Empty)
            };
        }

        // fin promociones
        #endregion


        public ListadoProyectoEspecialModel obtenerListadoProyectoEspecial()
        {
            return new ListadoProyectoEspecialModel
            {
                Listado = ProyectoEspecialDAO.obtenerListado()
            };
        }
        #region Validación Promociones
        private bool validarPromocion(Promocion promocion)
        {
            if (String.IsNullOrEmpty(promocion.Codigo)) {
                throw new DatoInvalidoException("Ingresar código de promoción");
            }

            if (String.IsNullOrEmpty(promocion.Descripcion))
            {
                throw new DatoInvalidoException("Debe ingresar la descripción");
            }

            if ((promocion.Detalle == null) || (promocion.Detalle.Count == 0))
            {
                throw new DatoInvalidoException("Debe agregar al menos un detalle de promoción");
            }

            foreach (var item in promocion.Detalle)
            {
                if ((item.Condiciones == null) || (item.DiasValidos == null) || (item.PorcentajeDescuento < 0) || (item.Restricciones == null))
                {
                    throw new DatoInvalidoException("Debe llenar todos los campos del detalle");
                }
            }

            return true;
        }
        #endregion

        #region Validación Contratos
        private bool validarContrato(Contrato contrato)
        {
            return true;
        }
        #endregion

        #region Validación CONVENIOS
        private bool validarConvenio(Convenio nuevoConvenio)
        {
            if (String.IsNullOrEmpty(nuevoConvenio.Codigo))
            {
                throw new DatoInvalidoException("Debe ingresar un código válido");
            }
            if (nuevoConvenio.Cliente == null || nuevoConvenio.Cliente.Codigo < 1)
            {
                throw new DatoInvalidoException("Debe seleccionar un solicitante");
            }
            //REGLA DE NEGOCIO
            if (ConvenioDAO.buscarClienteAsignado(nuevoConvenio.Cliente))
            {
                throw new DatoInvalidoException("Cliente ya ha sido asignado a un convenio activo");
            }
            //REGLA DE NEGOCIO
            if (nuevoConvenio.FechaFirma > nuevoConvenio.FechaVigencia) {
                throw new FechaInvalidoException("La Fecha de vigencia no puede ser mayor que la fecha de la firma del convenio.");
            }
            if (nuevoConvenio.FechaFirma < DateTime.Now.Subtract(TimeSpan.FromHours(DateTime.Now.Hour)) || nuevoConvenio.FechaVigencia > DateTime.Now.AddYears(1))
            {
                throw new RangoFechaInvalidoException("La fecha de vigencia del convenio debe ser establecido entre la fecha de hoy hasta un plazo de un año como máximo");
            }
            if (nuevoConvenio.FechaVigencia < DateTime.Now.AddMonths(6))
            {
                throw new RangoFechaInvalidoException("Las fecha de vigencia debe ser como mínimo 6 meses");
            }
            if (String.IsNullOrEmpty(nuevoConvenio.Descripcion))
            {
                throw new DatoInvalidoException("Debe ingresar la descripción");
            }

            if (String.IsNullOrEmpty(nuevoConvenio.NombreFuncionario))
            {
                throw new DatoInvalidoException("Debe ingresar el nombre del funcionario");
            }

            if (nuevoConvenio.Cliente.Codigo < 1)
            {
                throw new DatoInvalidoException("Debe seleccionar un cliente");
            }

            if ((nuevoConvenio.Detalle == null) || (nuevoConvenio.Detalle.Count == 0))
            {
                throw new DatoInvalidoException("Debe agregar al menos un detalle de convenio");
            }
            else
            {
                foreach (ConvenioDetalle d in nuevoConvenio.Detalle)
                {
                    if (d.PorcentajeDescuento < 0 || d.PorcentajeDescuento > 100)
                    {
                        throw new DatoInvalidoException("Debe ingresar un procentaje válido [0-100]");
                    }
                    //REGLA DE NEGOCIO
                    if (d.FlagExoneracionPago && String.IsNullOrEmpty(d.Beneficiados))
                    {
                        throw new DatoInvalidoException("Debe ingresar los beneficiados");
                    }
                    else
                    {
                        if (String.IsNullOrEmpty(d.Beneficiados))
                        {
                            d.Beneficiados = string.Empty;
                        }
                        else
                        {
                            throw new DatoInvalidoException("No se debe especificar el campo de beneficiados, sí no se marco el check de exoneración de pagos");
                        }
                    }
                    if (String.IsNullOrEmpty(d.Clausula))
                    {
                        throw new DatoInvalidoException("Debe ingresar una cláusula válida");
                    }

                    if (String.IsNullOrEmpty(d.PreRequisitos))
                    {
                        throw new DatoInvalidoException("Debe ingresar los requisitos");
                    }
                }
            }
            return true;
        }
        #endregion


        #region Validación Proyectos Especiales
        private bool validarProyectoEspecial(ProyectoEspecial pryEsp)
        {
            if (String.IsNullOrEmpty(pryEsp.Descripcion))
            {
                throw new DatoInvalidoException("Debe ingresar una descripcion del proyecto especial");
            }

            if (pryEsp.Cliente.Codigo < 1)
            {
                throw new DatoInvalidoException("Debe seleccionar un solicitante");
            }            

            if (pryEsp.Detalle == null || pryEsp.Detalle.Count == 0)
            {
                throw new DatoInvalidoException("Debe añadir un item del detalle de proyectos especiales");
            }
            else
            {
                foreach (ProyectoEspecialDetalle p in pryEsp.Detalle)
                {
                    if (String.IsNullOrEmpty(p.Servicio))
                        throw new DatoInvalidoException("Debe seleccionar un servicios");
                    if (String.IsNullOrEmpty(p.Tramo))
                        throw new DatoInvalidoException("Debe seleccionar un tramo");
                    if (p.FechaViaje < DateTime.Now.AddDays(1))
                        throw new DatoInvalidoException("Debe ingresar una fecha mayor a la fecha actual");
                    if (p.CantidadPasajeros <= 0 || p.CantidadPasajeros >= 1000)
                        throw new DatoInvalidoException("Debe ingresar la cantidad de pasajeros permitidos [1-999]");
                    if (String.IsNullOrEmpty(p.PuntoPartida))
                        throw new DatoInvalidoException("Debe ingresar el punto de partida");
                    if (String.IsNullOrEmpty(p.PuntoLlegada))
                        throw new DatoInvalidoException("Debe ingresar el punto de llegada");
                }
            }
            return true;
        }
        #endregion
    }
}